package com.app.protocol;

import com.app.exception.GPSDataVertifyFailException;

import soft.common.BitCheckUtil;
import soft.ifs.IByteBuff;
import soft.ifs.IParseBuild;
import soft.net.exception.DecodeDataFailException;
import soft.net.model.AReadNetStream;

/**
 * GPS协议
 * 
 * 时间A4 + 纬度B4+经度C4 + 速度D1 +方向东西经、南北纬E1+ 定位状态以及天线状态司机编码F1 + 里程G3 + 终端状态H3 +
 * 报警位I4 + 异或校验J1
 * 
 * @author fanpei
 *
 */
/**
 * @author fanpei
 *
 */
/**
 * @author fanpei
 *
 */
public class ProtocolGPS extends AReadNetStream implements IParseBuild {

	/**
	 * 大小固定为26字节
	 */
	public static final int SIZE = 26;

	/**
	 * (0-3) 时间
	 * 
	 * 表示从2000 年1 月1 日凌晨开始多少秒 （单位秒，格林威治时间）例如：0x07FCE8FF 表示 04 年3 月31 日02 点27 分11
	 * 秒（注意是格林威治时间）
	 * 
	 * @Size 4个字节
	 */
	private byte[] pasttime;

	/**
	 * (4-7) 纬度
	 * 
	 * @Size 4 个字节
	 */
	private byte[] latitude;

	/**
	 * (8-11) 经度
	 * 
	 * @Size 4 个字节
	 */
	private byte[] longitude;

	/**
	 * (12) 速度：1 个字节，（0x00-0x7F 连续）单位节 注意预留D7 作为冗余位（日后定义使用）
	 */
	private byte speed;

	/**
	 * (13) 方向＋GPS 标志：1 个字节（排列顺序：D7D6D5D4D3D2D1D0），其中D5D4D3D2D1D0 六位（0～36）用于表示
	 * 方向，单位为10°（正北为0°顺时针转）
	 * 
	 * @D7D6 D7D6 两位用于表示GPS 标志：(范围0-3)，
	 * @Define 具体定义为： 北纬东经(0) 北纬西经(1) 南纬东经(2) 南纬西经(3)
	 * @D6 D6 表示经度变化01 0 1
	 * @D7 D7表示纬度变化 0 0 1 1
	 */
	private byte direcGPSFlag;

	/**
	 * (14) GPS 天线状态＋定位状态＋司机编号
	 */
	private byte gpsStatusDriverCode;

	/**
	 * (15-17) 累积里程
	 * 
	 * @dsrc 0x000000－0xFFFFFF，单位1/76 公里； 例如：0x00001D 表示累积里程为：0x1D/76=0.3816公里
	 * 
	 * @Size 3 个字节
	 */
	private byte[] accumulatedMile;

	/**
	 * (18-20)终端状态
	 * 
	 * @Size 3 个字节
	 */
	private byte[] clientStatus;

	/**
	 * (21-24) 报警
	 * 
	 * @Size 4 个字节
	 */
	private byte[] alarmFlag;

	/**
	 * (25) 异或取反校验
	 */
	private byte parity;

	public byte[] getPasttime() {
		return pasttime;
	}

	public void setPasttime(byte[] pasttime) {
		this.pasttime = pasttime;
	}

	public byte[] getLatitude() {
		return latitude;
	}

	public void setLatitude(byte[] latitude) {
		this.latitude = latitude;
	}

	public byte[] getLongitude() {
		return longitude;
	}

	public void setLongitude(byte[] longitude) {
		this.longitude = longitude;
	}

	public byte getSpeed() {
		return speed;
	}

	public void setSpeed(byte speed) {
		this.speed = speed;
	}

	public byte getDirecGPSFlag() {
		return direcGPSFlag;
	}

	public void setDirecGPSFlag(byte direcGPSFlag) {
		this.direcGPSFlag = direcGPSFlag;
	}

	public byte getGpsStatusDriverCode() {
		return gpsStatusDriverCode;
	}

	public void setGpsStatusDriverCode(byte gpsStatusDriverCode) {
		this.gpsStatusDriverCode = gpsStatusDriverCode;
	}

	public byte[] getAccumulatedMile() {
		return accumulatedMile;
	}

	public void setAccumulatedMile(byte[] accumulatedMile) {
		this.accumulatedMile = accumulatedMile;
	}

	public byte[] getClientStatus() {
		return clientStatus;
	}

	public void setClientStatus(byte[] clientStatus) {
		this.clientStatus = clientStatus;
	}

	public byte[] getAlarmFlag() {
		return alarmFlag;
	}

	public void setAlarmFlag(byte[] alarmFlag) {
		this.alarmFlag = alarmFlag;
	}

	public byte getParity() {
		return parity;
	}

	public void setParity(byte parity) {
		this.parity = parity;
	}

	public ProtocolGPS() {
		pasttime = new byte[4];
		latitude = new byte[4];
		longitude = new byte[4];
		accumulatedMile = new byte[3];
		clientStatus = new byte[3];
		clientStatus = new byte[3];
	}

	/**
	 * 数据校验
	 * 
	 * @throws GPSDataVertifyFailException
	 */
	public void validate() throws GPSDataVertifyFailException {
		byte xorResult = buildCheckBit();
		if (xorResult != parity)
			throw new GPSDataVertifyFailException("数据校验失败");

	}

	@Override
	public void parse(IByteBuff in) throws DecodeDataFailException {
		if (in.readableBytes() == SIZE) {
			in.readBytes(pasttime);
			in.readBytes(latitude);
			in.readBytes(longitude);
			speed = in.readByte();
			direcGPSFlag = in.readByte();
			gpsStatusDriverCode = in.readByte();
			in.readBytes(accumulatedMile);
			in.readBytes(clientStatus);
			in.readBytes(alarmFlag);
			parity = in.readByte();
		}
	}

	@Override
	public byte[] build() {
		byte[] sends = new byte[SIZE];
		System.arraycopy(pasttime, 0, sends, 0, 4);
		System.arraycopy(latitude, 0, sends, 4, 4);
		System.arraycopy(longitude, 0, sends, 8, 4);
		System.arraycopy(speed, 0, sends, 12, 1);
		System.arraycopy(direcGPSFlag, 0, sends, 13, 1);
		System.arraycopy(gpsStatusDriverCode, 0, sends, 14, 1);
		System.arraycopy(accumulatedMile, 0, sends, 15, 3);
		System.arraycopy(clientStatus, 0, sends, 18, 3);
		System.arraycopy(alarmFlag, 0, sends, 21, 3);
		System.arraycopy(buildCheckBit(), 0, sends, 24, 1);
		return sends;
	}

	/**
	 * 获取异校验位
	 * 
	 * @return
	 */
	private byte buildCheckBit() {
		byte xorResult = BitCheckUtil.xorCheck(pasttime[0], pasttime);
		xorResult = BitCheckUtil.xorCheck(xorResult, latitude);
		xorResult = BitCheckUtil.xorCheck(xorResult, longitude);
		xorResult = BitCheckUtil.xorCheck(xorResult, speed);
		xorResult = BitCheckUtil.xorCheck(xorResult, direcGPSFlag);
		xorResult = BitCheckUtil.xorCheck(xorResult, gpsStatusDriverCode);
		xorResult = BitCheckUtil.xorCheck(xorResult, accumulatedMile);
		xorResult = BitCheckUtil.xorCheck(xorResult, clientStatus);
		xorResult = BitCheckUtil.xorCheck(xorResult, alarmFlag);
		xorResult = (byte) ~xorResult;
		return xorResult;
	}

}
